﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;


namespace Starfox
{
    class Player : GameObject3D
    {
        public float DirecaoFrontalX { get; set; }
        public float DirecaoFrontalY { get; set; }

        public const float Velocidade = 0.1f;
        public const float VelocidadeCurva = 0.004f;

        //variavel que determina a rotação X da nave
        float rotacaoX;
        //variavel que determina a rotação Z da nave
        float rotacaoZ;

        //variavel que determina a rotação maxima X da nave
        float rotacaoXMax;
        //variavel que determina a rotação  maxima Z da nave
        float rotacaoZMax;

        //variavel que determina a posição da nave
        Vector3 navePos;

        //mira
        Texture2D mira;

        //Vector que determina a posição da mira
        Vector2 posi_mira;

        //variavel que determina a velocidade da nave
        float velocidade_nave;
        //variavel que determina a maior velocidade que a nave pode ter
        float velocidade_nave_Max;

       

        KeyboardState teclado_atual, teclado_anterior;
        MouseState mouse_atual, mouse_anterior;


        Tiro tiro;
        bool atirar = true;

        public Player(GraphicsDevice graphicsDevice, ContentManager Content, GameWindow Window, BasicCamera camera)
            : base()
        {
            //Carrega o modelo da nave
            this.Model = Content.Load<Model>("SpaceShooter/Space_Shooter");

            //carrega(Load) a mira
            mira = Content.Load<Texture2D>("Textures/mira");
           
            DirecaoFrontalX = 0.0f;

            //determina a posição inicial da nave
            navePos = new Vector3(0, 10, -25);

            //determina a rotação maxima x
            rotacaoXMax = 30;
            //determina a rotação maxima y
            rotacaoZMax = 30;

            //determina a posição inicial da mira
            posi_mira = new Vector2(Window.ClientBounds.Width/2 - mira.Bounds.Width/2, Window.ClientBounds.Height/2 -mira.Bounds.Height/2 + 50);

            //determina a velocidade inicial da nave
            velocidade_nave = 10;

            //determina a velocidade maxima da nave
            velocidade_nave_Max = 20;

            tiro = new Tiro(graphicsDevice, Content, Window, camera, new Vector3(navePos.X, navePos.Y, 0));
        }
        public void Update(GameTime gameTime, GameWindow Window, bool AllRangeMode)
        {
            teclado_atual = Keyboard.GetState();
            teclado_anterior = teclado_atual;
            mouse_atual = Mouse.GetState();
            mouse_anterior = mouse_atual;

            tiro.Update(gameTime, Window);


            #region movimento
            
            //preciso testar *primeiro* se a posição futura é válida para não travar, por isso a guardo...
            Vector3 posicaoFutura = Posicao;

            //estas duas variáveis temporárias servem para o giro e o movimento
            float quantoVirar = 0;
            float quantoInclinar = 0;
            Vector3 movimento = Vector3.Zero;

            #region Movimentação_da_nave_pelo_mause

            float mouseDX = Window.ClientBounds.Width / 2 - mouse_atual.X;
            float mouseDY = Window.ClientBounds.Height / 2 - mouse_atual.Y;
            Mouse.SetPosition(Window.ClientBounds.Width / 2, Window.ClientBounds.Height / 2);
            
            quantoVirar = mouseDX;
            quantoInclinar = mouseDY;

            rotacaoX += quantoInclinar / 10;
            rotacaoZ -= quantoVirar / 10;

            if (rotacaoX < 0 & rotacaoX != 0 )
            {
                rotacaoX += 1;
            }
            if (rotacaoX > 0 & rotacaoX != 0)
            {
                rotacaoX -= 1;
            }
            if (rotacaoZ < 0 & rotacaoZ != 0 )
            {
                rotacaoZ += 1;
            }
            if (rotacaoZ > 0 & rotacaoZ != 0 )
            {
                rotacaoZ -= 1;
            }

            if (rotacaoZ >= rotacaoZMax) rotacaoZ = rotacaoZMax;

            if (rotacaoZ <= -rotacaoZMax) rotacaoZ = -rotacaoZMax;

            if (rotacaoX >= rotacaoXMax) rotacaoX = rotacaoXMax;

            if (rotacaoX <= -rotacaoXMax) rotacaoX = -rotacaoXMax;

            if (mouse_atual.LeftButton == ButtonState.Pressed)
            {
                atirar = true;
            };

            
            #region Velocidade
            //turbo

            if (teclado_atual.IsKeyDown(Keys.W))
            {
                velocidade_nave *= 1.1f;
            }
            if (teclado_atual.IsKeyDown(Keys.S))
            {
                velocidade_nave -= 1;
            }

            if (velocidade_nave >= velocidade_nave_Max) velocidade_nave = velocidade_nave_Max;

            if (velocidade_nave <= 5) velocidade_nave = 5;

            if (velocidade_nave > 10 & teclado_atual.IsKeyUp(Keys.W))
            {
                velocidade_nave -= 1;
            }

            if (velocidade_nave < 10 & teclado_atual.IsKeyUp(Keys.S))
            {
                velocidade_nave += 1;
            }

            // aceleração permanente
            movimento.Z -= velocidade_nave;



            #endregion
            #endregion

            

            #region Movimentação_da_nave_pelo_teclado

            

            #region Controles_da_nave_e_da_mira
/*
            if (teclado_atual.IsKeyDown(Keys.W))
            {
                atirar = true;
            }
            
            if (teclado_atual.IsKeyDown(Keys.S))
            {
                quantoInclinar -= 10;
                rotacaoX -= 1;
                posi_mira.Y += 8;
            }            
            if (teclado_atual.IsKeyDown(Keys.A))
            {
                quantoVirar += 10;
                rotacaoZ -= 3;
                posi_mira.X -= 8;
            }
            if (teclado_atual.IsKeyDown(Keys.D))
            {
                quantoVirar -= 10;
                rotacaoZ += 3;
                posi_mira.X += 8;
            }           
            #endregion

            #region Controle_de_rotação_ e_ posição_da_nave

            if (rotacaoX < 0 & rotacaoX != 0 & teclado_atual.IsKeyUp(Keys.S))
            {
                rotacaoX += 1;
            }
            if (rotacaoX > 0 & rotacaoX != 0 & teclado_atual.IsKeyUp(Keys.W))
            {
                rotacaoX -= 1;
            }
            if (rotacaoZ < 0 & rotacaoZ != 0 & teclado_atual.IsKeyUp(Keys.A))
            {
                rotacaoZ += 1;
            }
            if (rotacaoZ > 0 & rotacaoZ != 0 & teclado_atual.IsKeyUp(Keys.D))
            {
                rotacaoZ -= 1;
            }

            if (rotacaoZ >= rotacaoZMax) rotacaoZ = rotacaoZMax;

            if (rotacaoZ <= -rotacaoZMax) rotacaoZ = -rotacaoZMax;

            if (rotacaoX >= rotacaoXMax) rotacaoX = rotacaoXMax;

            if (rotacaoX <= -rotacaoXMax) rotacaoX = -rotacaoXMax;

            #endregion
             
             //  aceleração permanente
            movimento.Z -= 10;
             
            */

            #endregion

            //o pra onde ele vai virar é corrigido pela velocidade de giro
            if (AllRangeMode) DirecaoFrontalX += quantoVirar * VelocidadeCurva; else navePos.X -= (quantoVirar * Velocidade / 3);
            navePos.Y += (quantoInclinar * Velocidade / 3);

            //isto está aqui apenas pq esta variável tem outro nome na hora de desenhar...
            if (AllRangeMode) RotacaoY = DirecaoFrontalX; else RotacaoY = navePos.X;
            RotacaoX = navePos.Y;

            //preciso girar meu objeto naquela direção antes de andar
            Matrix matrixOrientacao = Matrix.CreateRotationX(DirecaoFrontalY) * Matrix.CreateRotationY(DirecaoFrontalX);

            //ando com ele aquela quantidade de movimento naquela direcao de orientacao
            Vector3 velocidade = Vector3.Transform(movimento, matrixOrientacao);
            
            //corrijo pela escala da velocidade
            velocidade *= Velocidade;

            //agora sim esta será a nova posicao do objeto
            posicaoFutura = Posicao + velocidade;
            //

            if (posicaoFutura.X > 100) { posicaoFutura.X = 100; }
            Console.WriteLine(mouse_atual.X);
          
            Posicao = posicaoFutura;

            posi_mira.X -= mouseDX;
            posi_mira.Y -= mouseDY;
          
            #endregion

            Quaternion rodarModelo = Quaternion.CreateFromYawPitchRoll(DirecaoFrontalX, DirecaoFrontalY, 0);
            this.World = Matrix.CreateScale(0.7f) 
                * Matrix.CreateRotationZ(MathHelper.ToRadians(rotacaoZ)) 
                * Matrix.CreateRotationY(MathHelper.ToRadians(180)) 
                * Matrix.CreateRotationX(MathHelper.ToRadians(rotacaoX)) 
                * Matrix.CreateTranslation(navePos) 
                * Matrix.CreateFromQuaternion(rodarModelo) 
                * Matrix.CreateTranslation(Posicao); 
            #endregion         
        }

        public void Draw(GameTime gameTime, BasicCamera camera, SpriteBatch spriteBatch, GameWindow Window)
        {
            //desenha o modelo
            this.Desenhar(camera);
            
            //desenha a mira
            spriteBatch.Draw(mira, posi_mira, Color.White);

            if (atirar)
            { 
                tiro.Draw(gameTime, camera, spriteBatch, Window);
                atirar = false;
            }
            
        }

        
 
        
        
    }
}